/**
 * 
 */
package hamburgerwang.common;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author harry.g.wang
 * 
 */
public class HttpHelper {

	private String encoding;
	private static boolean usingProxy = false;
	private static Proxy proxy;

	public static void setProxy(String host, int port) {
		if (host != null && host.trim().length() > 0) {
			usingProxy = true;
			proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
					host, port));
		} else {
			usingProxy = false;
		}
	}

	public String getEncoding() {
		return this.encoding;
	}

	public void setEncoding(String value) {
		this.encoding = value;
	}

	public HttpHelper() {
		this.encoding = "UTF-8";
	}

	public String Get(String url) throws IOException {
		return Request(url, false, null, null, true);
	}

	public String Post(String url, Map<String, String> postData)
			throws IOException {
		return Request(url, true, postData, null, true);
	}

	private String Request(String urlString, boolean isPost,
			Map<String, String> data, Map<String, String> headers,
			boolean withTry) throws IOException {

		// Create a request using a URL that can receive a post.
		URL url = new URL(urlString);
		HttpURLConnection connection;
		if (usingProxy) {
			connection = (HttpURLConnection) url.openConnection(proxy);
		} else {
			connection = (HttpURLConnection) url.openConnection();
		}
		connection.setUseCaches(false);

		// Set the Method property of the request to POST.
		connection.setRequestMethod(isPost ? "POST" : "GET");
		// Set the ContentType property of the WebRequest.
		connection.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");
		if (isPost) {
			// Set the ContentLength property of the WebRequest.
			StringBuilder postData = new StringBuilder();
			Iterator<Entry<String, String>> enumerator = data.entrySet()
					.iterator();
			while (enumerator.hasNext()) {
				Entry<String, String> pair = enumerator.next();
				if (postData.length() > 0) {
					postData.append('&');
				}
				postData.append(pair.getKey()).append('=').append(
						URLEncoder.encode(pair.getValue(), this.encoding));
			}

			connection.setDoOutput(true);
			connection.setDoInput(true);

			// Get the request stream.
			DataOutputStream dataStream = new DataOutputStream(connection
					.getOutputStream());
			// Write the data to the request stream.
			dataStream.writeBytes(postData.toString());
			// Close the Stream object.
			dataStream.close();
		}
		// Get the response.
		InputStream response = connection.getInputStream();

		// Open the stream using a StreamReader for easy access.
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				response, this.encoding));

		// Read the content.
		try {
			StringBuilder responseFromServer = new StringBuilder();
			String line;
			while ((line = reader.readLine()) != null) {
				responseFromServer.append(line);
			}
			// Clean up the streams.
			return responseFromServer.toString();
		} finally {
			reader.close();
			response.close();
		}
	}

	public static String GetSessionID(String cookies) {
		Pattern pattern = Pattern.compile("ASP\\.NET_SessionId\\=([^;]*)\\;.*",
				RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
		Matcher match = pattern.matcher(cookies);
		if (match.matches()) {
			return match.group(1);
		} else {
			throw new RuntimeException("Cookie not found");
		}
	}

	public static String GetHtmlFieldValue(String html, String fieldName,
			String tagName) {
		Pattern pattern = Pattern.compile(String.format(
				"\\<%1$s\\b[^\\<]*id\\=\"%2$s\"[^\\<]*value=\"([^\"]*)\"",
				tagName, fieldName), RegexOptions.IgnoreCase
				| RegexOptions.ExplicitCapture);
		Matcher match = pattern.matcher(html);
		if (match.find()) {
			return match.group(1);
		} else {
			return "";
		}
	}

	public static String GetUpdatePanelFieldValue(String html, String fieldName) {
		Pattern pattern = Pattern.compile(String.format("%1$s\\|([^\\|]*?)\\|",
				fieldName), RegexOptions.IgnoreCase
				| RegexOptions.ExplicitCapture);
		Matcher match = pattern.matcher(html);
		if (match.find()) {
			return match.group(1);
		} else {
			return "";
		}
	}

	public static String GetHtmlFieldInnerHtml(String html, String fieldName,
			String tagName) {
		Pattern pattern = Pattern.compile(String.format(
				"\\<%1$s\\b[^\\<]*id\\=\"%2$s\"[^\\>]*>(.*?)\\<\\/%1$s\\>",
				tagName, fieldName), RegexOptions.IgnoreCase
				| RegexOptions.ExplicitCapture | RegexOptions.Singleline);
		Matcher match = pattern.matcher(html);
		if (match.find()) {
			return match.group(1).replace("&nbsp;", " ");
		} else {
			return "";
		}
	}

	public static String[] GetHtmlFieldInnerHtml(String html, String tagName) {
		Pattern pattern = Pattern.compile(String.format(
				"\\<%1$s\\b[^\\>]*>(.*?)\\<\\/%1$s\\>", tagName),
				RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
						| RegexOptions.Singleline);
		Matcher match = pattern.matcher(html);

		List<String> list = new ArrayList<String>();
		while (match.find()) {
			list.add(match.group(1).replace("&nbsp;", ""));
		}
		String[] array = new String[list.size()];
		return list.toArray(array);
	}

	public class RegexOptions {
		public static final int IgnoreCase = Pattern.CASE_INSENSITIVE;

		public static final int Singleline = Pattern.DOTALL;

		public static final int ExplicitCapture = 0;
	}
}
